#ifndef _USER_GAMELOG_MAMANAGER_H_
#define _USER_GAMELOG_MAMANAGER_H_

#include "Common.h"
#include "Resource.h"
#include "ResourceManager.h"
#include "Singleton.h"
#include "String.h"
#include "Database/Field.h"
#include "DataManager.h"
#include "Threading/Mutex.h"
#include "Users.h"

#define DB_NAME_USERGAMELOGS		"user_game_logs"

class  Database;
class  CharPtr;
class  WSSocketPtr;
class  UserPtr;

typedef struct user_game_log_tag_
{
	uint64 log_id;			//日志ID（主键）
	uint32 group_id;		//服务器组ID
	uint32 server_id;		//服务器ID
	uint32 agent_id;		//代理商ID
	uint32 gz_id;			//分区ID
	
	String game_name;		//游戏名称
	uint32 status;			//状态（1 正常 255 删除）
	
	uint32 type;			//日志主类型
	uint32 sub_type;		//日志子类型
	uint32 flag;			//标志
	uint32 platform_id;		//玩家PID
	
	String user_name;		//玩家名字
	String user_nick;		//玩家昵称
	
	uint32 src_id;			//源目标ID
	uint32 src_type;		//源目标类型
	
	uint32 dest_id;			//目标对象ID
	uint32 dest_type;		//目标对象类型
	
	uint32 target_id;		//对象ID
	uint32 target_type;		//对象类型
	
	uint32 change_model_id;	//改变道具模式ID
	int32 change_num;		//改变数量
	uint32 org_num;			//变化前数量
	uint32 end_num;			//变化后数量
	uint32 congeal_num;		//冻结数量
	uint32 town_id;			//房间ID
	uint32 channel_id;		//牌桌ID
	String last_ip;			//最后ip
	uint32 last_time;		//最后时间
	
	int32 data1;			//有符号整形数据1
	int32 data2;			//有符号整形数据2
	int32 data3;			//有符号整形数据3
	int32 data4;			//有符号整形数据4
	int32 data5;			//有符号整形数据5
	int32 data6;			//有符号整形数据6
	int32 data7;			//有符号整形数据7
	int32 data8;			//有符号整形数据8
	
	uint32 udata1;			//无符号整形数据1
	uint32 udata2;			//无符号整形数据2
	uint32 udata3;			//无符号整形数据3
	uint32 udata4;			//无符号整形数据4
	uint32 udata5;			//无符号整形数据5
	uint32 udata6;			//无符号整形数据6
	uint32 udata7;			//无符号整形数据7
	uint32 udata8;			//无符号整形数据8
	
	int64 ldata1;			//有符号长整形数据1
	int64 ldata2;			//有符号长整形数据2
	int64 ldata3;			//有符号长整形数据3
	int64 ldata4;			//有符号长整形数据4
	
	uint64 ludata1;			//无符号长整形数据1
	uint64 ludata2;			//无符号长整形数据2
	uint64 ludata3;			//无符号长整形数据3
	uint64 ludata4;			//无符号长整形数据4
	
	float fdata1;			//浮点数据1
	float fdata2;			//浮点数据2
	float fdata3;			//浮点数据3
	float fdata4;			//浮点数据4

	String sdata1;			//整形数据1
	String sdata2;			//整形数据2
	String sdata3;			//整形数据3
	String sdata4;			//整形数据4
	String sdata5;			//整形数据5
	String sdata6;			//整形数据6
	String sdata7;			//整形数据7
	String sdata8;			//整形数据8
	
	String user_data;		//用户数据
	String info;			//备注信息
	String create_time;		//日志创建时间

	
	user_game_log_tag_()
	{
		Init();
	}
	
	void Init()
	{
		log_id = 0;
		group_id = 0;
		server_id = 0;
		agent_id = 0;
		gz_id = 0;
		game_name = "";
		status = 0;
		type = 0;
		sub_type = 0;
		flag = 0;
		platform_id = 0;
		user_name = "";
		user_nick = "";
		src_id = 0;
		src_type = 0;
		dest_id = 0;
		dest_type = 0;
		target_id = 0;
		target_type = 0;
		change_model_id = 0;
		
		change_num = 0;
		org_num = 0;
		end_num = 0;
		congeal_num = 0;
		town_id = 0;
		channel_id = 0;
		last_ip = "";
		last_time = 0;
		
		data1 = 0;
		data2 = 0;
		data3 = 0;
		data4 = 0;
		data5 = 0;
		data6 = 0;
		data7 = 0;
		data8 = 0;
		
		udata1 = 0;
		udata2 = 0;
		udata3 = 0;
		udata4 = 0;
		udata5 = 0;
		udata6 = 0;
		udata7 = 0;
		udata8 = 0;
		
		ldata1 = 0;
		ldata2 = 0;
		ldata3 = 0;
		ldata4 = 0;
		ludata1 = 0;
		ludata2 = 0;
		ludata3 = 0;
		ludata4 = 0;
		
		fdata1 = 0.0f;
		fdata2 = 0.0f;
		fdata3 = 0.0f;
		fdata4 = 0.0f;
		
		sdata1 = "";
		sdata2 = "";
		sdata3 = "";
		sdata4 = "";
		sdata5 = "";
		sdata6 = "";
		sdata7 = "";
		sdata8 = "";
		
		user_data = "";
		info = "";
		create_time = "";
	}
	
}UserGameLog;

// 登录登出日志参数结构
struct stLoginQutLog
{
	UserPtr pSrcUser;
	String ip;
	
	uint8 mode;	// 1 登录 2 退出
	stLoginQutLog()
	{
		Init();
	}
	
	void Init()
	{
		pSrcUser.setNull();
		ip = "";
		
		mode = 0;
	}
	
};

// 财富变化参数结构
struct stItemsChangeLog
{
	UserPtr pSrcUser;		// 生成日志源头对象
	UserPtr pDestUser;		// 输赢钱给玩家的目标对象
	
	uint8 sub_type;			// 子类型
	uint32 change_model_id;	// 改变的道具模式ID
	int32 change_num;		// 改变数量（目标对象输或者赢源对象数量）有正负
	uint32 org_num;			// 改变前数量
	uint32 end_num;			// 改变后数量
	uint32 congeal_num;		// 冻结数量
	uint32 town_id;			// 房间ID
	uint32 channel_id;		// 牌桌ID
	
	uint32 extra_data1;		// 附加数据1
	uint32 extra_data2;		// 附加数据2
	
	String info;			// 日志内容描述
	
	stItemsChangeLog()
	{
		Init();
	}
	
	void Init()
	{
		pSrcUser.setNull();
		pDestUser.setNull();
		
		sub_type = 0;
		change_model_id = 0;
		change_num = 0;
		org_num = 0;
		end_num = 0;
		congeal_num = 0;
		town_id = 0;
		channel_id = 0;
		extra_data1 = 0;
		extra_data2 = 0;
		
		info = "";
	}
};

// 经验变化日志结构
struct stExpsChangeLog
{
	UserPtr pSrcUser;
	String ip;
	
	stExpsChangeLog()
	{
		Init();
	}
	
	void Init()
	{
		pSrcUser.setNull();
		ip = "";
	}
	
};

// 玩家组局输赢日志结构
struct stPlayerCBResultInfo
{
	UserPtr pUser;			// 玩家
	
	uint32 cb_id;			// 组局ID
	uint32 game_id;			// 游戏ID
	uint32 gz_id;			// 分区ID
	uint32 loop;			// 游戏局数
	uint32 roomOwner;		// 是否房主
	int32 winlose_score;	// 输赢积分
	uint32 top_times;		// 封顶倍数
	uint32 isPlayAll;		// 是否完成所有局数
	uint32 finish_status;	// 完成状态
	uint32 mode;			// 游戏玩法
	String strJoinCode;		// 房间验证码
	String info;			// 日志内容
	
	stPlayerCBResultInfo()
	{
		Init();
	}
	
	void Init()
	{
		pUser.setNull();
		cb_id = 0;
		game_id = 0;
		gz_id = 0;
		loop = 0;
		roomOwner = 0;
		winlose_score = 0;
		top_times = 0;
		isPlayAll = 0;
		finish_status = 0;
		strJoinCode = "";
		info = "";
	}
	
};

// 财富变化参数结构
struct stGoldsChangeLog
{
	UserPtr pSrcUser;
	
	uint8 sub_type;			// 子类型
	uint32 change_model_id;	// 改变的道具模式ID
	int32 change_num;		// 改变数量
	uint32 org_num;			// 改变前数量
	uint32 end_num;			// 改变后数量
	
	String info;			// 日志内容
	
	stGoldsChangeLog()
	{
		Init();
	}
	
	void Init()
	{
		pSrcUser.setNull();
		
		sub_type = 0;
		change_model_id = 0;
		change_num = 0;
		org_num = 0;
		end_num = 0;
		
		info = "";
	}
};

// 组局日志结构
struct stCenterBattleLog
{
	UserPtr pUser;		// 玩家
	uint32 cb_id;		// 组局ID
	uint32 game_id;		// 游戏ID
	uint32 gz_id;		// 分区ID
	uint32 model_id;	// 开局费模式ID
	uint32 num;			// 开局费数量
	uint32 status;		// 状态（0 正常结束 1 重启结束 2 超时结束 4 创建失败 5 解散（未开局） 6 创建牌桌）
	uint32 loop;		// 完成的局数
	uint32 isPlayAll;	// 是否全部完成
	uint32 mode;		// 玩法模式
	
	String info;		// 日志内容
	
	stCenterBattleLog()
	{
		Init();
	}
	
	void Init()
	{
		pUser.setNull();
		cb_id = 0;
		game_id = 0;
		gz_id = 0;
		model_id = 0;
		num = 0;
		status = 0;
		loop = 0;
		isPlayAll = 0;
		mode = 0;
		
		info = "";
	}
};

struct stPlayerCBWinloseLog
{
	UserPtr pUser;		// 玩家
	
	uint32 cb_id;		// 组局ID
	uint32 game_id;		// 游戏ID
	uint32 gz_id;		// 分区ID
	uint32 curr_loop;	// 当前局数
	uint32 top_times;	// 封顶倍数
	uint32 mode;		// 游戏玩法
	uint32 extra_data1;	// 附加数据（牛牛填写的是牌型）
	
	int32 winlose_score;// 输赢积分
	
	String info;		// 日志内容
	
	stPlayerCBWinloseLog()
	{
		Init();
	}
	
	void Init()
	{
		pUser.setNull();
		
		cb_id = 0;
		game_id = 0;
		gz_id = 0;
		curr_loop = 0;
		top_times = 0;
		mode = 0;
		extra_data1 = 0;
		
		winlose_score = 0;
		
		info = "";
	}
};

enum enUserGameLogType
{
	enUserGameLogType_System = 0, 			// 系统相关类型
	enUserGameLogType_Login = 1, 			// 登录退出相关类型
	enUserGameLogType_Gold = 2, 			// 元宝变更
	enUserGameLogType_Exp = 3, 				// 经验
	enUserGameLogType_Item = 4, 			// 物品相关类型
	enUserGameLogType_Table = 5, 			// 牌桌相关类型
	enUserGameLogType_Figural = 6, 			// 改变形象
	enUserGameLogType_Mission = 7, 			// 任务
	enUserGameLogType_Practicality = 8, 	// 实物兑换
	enUserGameLogType_GatwayBuyResult = 9, 	// 网关购买物品结果
	enUserGameLogType_SMGame = 10,			// 小游戏日志
	enUserGameLogType_Morra = 11,			// 猜拳日志
	enUserGameLogType_TTLChannel = 12,		// 推推乐战场日志
	enUserGameLogType_ErrorProtocol = 13,	// 黑协议日志 
	enUserGameLogType_Pump = 14,			// 抽水
	enUserGameLogType_Fruit = 15,			// 水果机
	enUserGameLogType_UserDefined = 16,					// 游戏内自定义
	enUserGameLogType_Bank = 17, 						// 本地银行相关
	enUserGameLogType_Farm = 18, 						// 牧场相关类型
	enUserGameLogType_CardsType = 19, 					// 牌型相关日志
	enUserGameLogType_CenterBattle = 200, 				// 组局日志
	enUserGameLogType_PlayerCenterBattleResult = 201, 	// 玩家组局结果日志
	enUserGameLogType_PlayerCenterBattleWinlose = 202, 	// 玩家组局详细输赢日志
	enUserGameLogType_Error = 255						// 报错日志
};

// 登录登出日志子类型
enum enLoginLogSubType
{
	en_LLST_Login = 1,	// 登录
	en_LLST_Logout = 2,	// 退出
};

// 财富变化子类型
enum enItemChangeSubTpye
{
	
};

// 牌桌相关类型
enum enTableLogSubType
{
	en_TLST_Enter = 1, 		// 进入牌桌
	en_TLST_Offline = 2, 	// 中途掉线
	en_TLST_Return = 3, 	// 返回牌桌
	en_TLST_Run = 4, 		// 逃跑
	en_TLST_Complete = 5, 	// 完成游戏
	en_TLST_Result = 6,		// 完成牌局
};

#define WGS_GAMELOG_MUTEX_NAME gamelog_mutex
#define WGS_GAMELOG_MUTEX mutable boost::mutex WGS_GAMELOG_MUTEX_NAME;
#define WGS_GAMELOG_LOCK		boost::lock_guard<boost::mutex> wgsCenterGameLogMutexLock(WGS_GAMELOG_MUTEX_NAME);

//-------------------------组局信息-----------------------
class  SERVER_DECL UserGameLogManager:public Singleton<UserGameLogManager>
{
public:
	WGS_GAMELOG_MUTEX
	/**
	 * @创建时间 2017-03-28
	 * @创建人 Roach
	 * @函数作用 添加一条CenterGameRecord记录
	 * @参数
	 * 	@log	UserGameLog
	 */
	bool AddUserGameLog(UserGameLog & log);
	
	/**
	 * @创建时间 2017-03-28
	 * @创建人 Roach
	 * @函数作用 更新UserGameLog数据
	 * @参数
	 * 	@log_id	
	 *	@fields	字段键值对,格式：fields["key1"] = 1; fields["key2"] = 2;...
	 */
	bool UpdateUserGameLog(Fields * fields, const char * QueryString, ...);
	
	/**
	 * @创建时间 2017-03-28
	 * @创建人 Roach
	 * @函数作用 根据PD_ID获取一条PD数据
	 * @参数
	 *  @log_id 		UserGameLog log_id
	 * 	@record		UserGameLog对象
	 */
	bool GetUserGameLog(const uint64 &log_id, UserGameLog * record);
	
	/**
	 * @创建时间 2017-03-28
	 * @创建人 Roach
	 * @函数作用 获取记录列表
	 * @参数
	 * 	@lstData	UserGameLog对象列表
	 *  @query 		查询语句条件
	 */
	uint32 GetUserGameLogList(std::list<UserGameLog> * lstData, const char * query,...);
	
public:
	
	//========================日志类型记录===================================
	// 登录退出游戏日志
	bool LoginOrLogoutGameLog(UserPtr & pUser, enLoginLogSubType login_type, String info);
	// 财富变化日志（玩家之间）
	bool ItemsChangeLogWithUsers(stItemsChangeLog & parma);
	// 财富变化日志（系统）
	bool ItemsChangeLogWithSystem(stItemsChangeLog & parma);
	// 经验变化日志
	bool ExpsChangeLog(UserPtr & pUser, const uint8 & subType, const int32 & change_exps, String info);
	// 牌桌日志
	bool AboutTableLog(UserPtr & pUser, const uint32 & channelId, enTableLogSubType subType, String info);
	// 实物兑换日志
	bool ChangePracticalityLog(const uint32 userId, const uint32 goodsId, const String &name, const uint32 number, const uint32 cost, const char *billId);
	// 元宝更新日志
	bool UpdateGoldsFromGatewayLog(stGoldsChangeLog parma);
	// 改变形象日志
	bool ChangeFiguralLog(UserPtr & pUser, const uint8 sourceType, const uint32 figuralId, const uint32 fromId, String info);
	// 系统抽水日志
	bool SystemTaxationLog(const uint32 townId, const uint32 channelId, const uint32 ante, const uint32 multy, const uint32 taxation, const uint8 subType, String info);
	// 牌型日志
	bool GameCardsType(UserPtr & pUser, const uint32 & townId, const uint32 & channelId, const uint32 & cardType, 
								const uint32 & data1, const uint32 & data2, 
								String strCardType = "", String strCardsList = "",
								const uint32 & data3 = 0, const uint32 & data4 = 0);
	// 组局日志
	bool CreateCenterBattleLog(stCenterBattleLog cbl);
	// 玩家组局结果日志
	bool CenterBattleResultLog(stPlayerCBResultInfo pcb_info);
	// 组局玩家输赢日志
	bool CreatePlayerCenterBattleWinloseLog(stPlayerCBWinloseLog pcbl);
	
	// 水果机下注输赢日志
	// mapChipin 	下注详情
	// bounty_id	奖励ID
	// multi		奖励倍数
	// winLose		玩家输赢
	bool FruitGameResultLog(CharPtr & pChr, std::map<uint32, uint32> mapChipin,
							std::map<uint32, uint32> mapBounty,
							const int32 & winLose, const int32 & sys_winLose);
	
	// 房间库存变化日志
	bool TownKuCunChangeLog(const uint32 & town_id,
							const int32 & change_num,
							const uint32 & curr_num,
							const uint8 & sub_type);
	
	// 系统庄输赢日志
	bool SystemBankerWinLoseLog(const uint32 & town_id,
								const int32 & change_num,
								const uint32 & curr_num,
								const uint8 & sub_type);
	
	//========================日志类型记录===================================
	
	//========================周边逻辑支持===================================
	// 追加用户信息
	bool AppendUserInfo(UserGameLog & log, UserPtr & pUser);
	// 追加游戏名称和分区内容
	void AppendGameInfo(UserGameLog & log, String & info);
	//========================周边逻辑支持===================================
};

#define	 sCGLogMgr		 UserGameLogManager::getSingleton()

#endif	//_USER_GAMELOG_MAMANAGER_H_
